home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / dostimer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  24.1 KB  |  966 lines

  1. /*      dostimer.c
  2.  *
  3.  * MIDAS Sound System timer for MS-DOS
  4.  *
  5.  * $Id: dostimer.c,v 1.6 1997/01/16 18:41:59 pekangas Exp $
  6.  *
  7.  * Copyright 1996,1997 Housemarque Inc.
  8.  *
  9.  * This file is part of the MIDAS Sound System, and may only be
  10.  * used, modified and distributed under the terms of the MIDAS
  11.  * Sound System license, LICENSE.TXT. By continuing to use,
  12.  * modify or distribute this file you indicate that you have
  13.  * read the license and understand and accept it fully.
  14. */
  15.  
  16. #include <dos.h>
  17. #include "lang.h"
  18. #include "mtypes.h"
  19. #include "errors.h"
  20. #include "sdevice.h"
  21. #include "timer.h"
  22. #include "mglobals.h"
  23.  
  24. RCSID(const char *dostimer_rcsid = "$Id: dostimer.c,v 1.6 1997/01/16 18:41:59 pekangas Exp $";)
  25.  
  26. //#define TIMERBORDERS
  27.  
  28. /* Time between to screen interrupts is 96.5% of total frame time - the
  29.    interrupt comes somewhat before the Vertical Retrace actually starts: */
  30. #define FRAMETIME 965
  31.  
  32. /* Timer mode: */
  33. #define TIMERMODE 0x30
  34.  
  35. /* Maximum # of music players: */
  36. #define MAXPLAYERS 16
  37.  
  38.  
  39. static void (__interrupt __far *oldTimer)();
  40. static volatile int tmrState;
  41. static volatile int playSD;
  42.  
  43. static volatile long sysTmrCount;       /* system timer counter */
  44. static volatile long playTmrCount;      /* initial player timer count */
  45. static volatile long playCount;         /* player timer count */
  46. static volatile SoundDevice *sdev;      /* current SD */
  47.  
  48. static int CALLING (*musicPlayers[MAXPLAYERS])(void);    /* music players */
  49.  
  50. static volatile int playSD;             /* 1 if sound should be played */
  51. static volatile int plTimer;            /* 1 if player-timer is active */
  52. static volatile int plError;            /* music playing error code */
  53.  
  54. static volatile long scrCount;          /* screen timer counter */
  55. static volatile long scrTmrCount;       /* initial value for screen timer */
  56. static volatile long scrPVCount;        /* count before retrace */
  57.  
  58. static void CALLING (*preVR)();         /* pre-VR function */
  59. static void CALLING (*immVR)();         /* immVR() */
  60. static void CALLING (*inVR)();          /* inVR() */
  61.  
  62. static volatile int scrSync;            /* is timer synchronized to screen? */
  63. static volatile int scrTimer;           /* 1 if screen-timer is active */
  64. static volatile int scrPlayer;          /* synchronize player to screen? */
  65.  
  66. static volatile int tmrState;           /* timer state */
  67.  
  68.  
  69.  
  70.  
  71. /****************************************************************************\
  72. *       enum tmrStates
  73. *       --------------
  74. * Description:  Possible timer states
  75. \****************************************************************************/
  76.  
  77. enum tmrStates
  78. {
  79.     tmrSystem = 0,                      /* system timer */
  80.     tmrPlayer,                          /* music player */
  81.     tmrScreen                           /* display synchronized timer */
  82. };
  83.  
  84.  
  85.  
  86. void outp(unsigned port, unsigned value);
  87. #pragma aux outp = \
  88.     "out    dx,al" \
  89.     parm [edx] [eax] \
  90.     modify exact [];
  91.  
  92. unsigned inp(unsigned port);
  93. #pragma aux inp = \
  94.     "xor    eax,eax" \
  95.     "in     al,dx" \
  96.     parm [edx] \
  97.     value [eax] \
  98.     modify exact [eax];
  99.  
  100. void DoSTI(void);
  101. #pragma aux DoSTI = "sti" modify exact[];
  102.  
  103. void DoCLI(void);
  104. #pragma aux DoCLI = "cli" modify exact[];
  105.  
  106. void SendEOI(void);
  107. #pragma aux SendEOI = \
  108.     "   mov     al,20h" \
  109.     "   out     20h,al" \
  110.     modify exact[eax];
  111.  
  112.  
  113. /* Set border color: */
  114. #ifdef TIMERBORDERS
  115. void SetBorder(int color);
  116. #pragma aux SetBorder = \
  117.     "   mov     dx,03DAh" \
  118.     "   in      al,dx" \
  119.     "   mov     dx,03C0h" \
  120.     "   mov     al,31h" \
  121.     "   out     dx,al" \
  122.     "   mov     al,bl" \
  123.     "   out     dx,al" \
  124.     parm [ebx] \
  125.     modify exact [eax edx];
  126. #else
  127. #define SetBorder(x)
  128. #endif
  129.  
  130.  
  131. /* Wait for next Vertical Retrace: */
  132. void WaitNextVR(void);
  133. #pragma aux WaitNextVR = \
  134.     "   mov     dx,03DAh" \
  135.     "n: in      al,dx" \
  136.     "   test    al,8" \
  137.     "   jnz     n" \
  138.     "v: in      al,dx" \
  139.     "   test    al,8" \
  140.     "   jz      v" \
  141.     modify exact [eax edx];
  142.  
  143. /* Wait for Vertical Retrace: */
  144. void WaitVR(void);
  145. #pragma aux WaitVR = \
  146.     "   mov     dx,03DAh" \
  147.     "w: in      al,dx" \
  148.     "   test    al,8" \
  149.     "   jz      w" \
  150.     modify exact [eax edx];
  151.  
  152. /* Wait for no Vertical Retrace: */
  153. void WaitNoVR(void);
  154. #pragma aux WaitNoVR = \
  155.     "   mov     dx,03DAh" \
  156.     "w: in      al,dx" \
  157.     "   test    al,8" \
  158.     "   jnz     w" \
  159.     modify exact [eax edx];
  160.  
  161. /* Set DS to ES: */
  162. void SetDStoES(void);
  163. #pragma aux SetDStoES = \
  164.     "   mov     ax,ds" \
  165.     "   mov     es,ax" \
  166.     modify exact [eax];
  167.  
  168.  
  169.  
  170. /****************************************************************************\
  171. *
  172. * Function:     void SetCount(unsigned count)
  173. *
  174. * Description:  Sets new timer count
  175. *
  176. * Input:        unsigned count          new timer count
  177. *
  178. \****************************************************************************/
  179.  
  180. static void SetCount(unsigned count)
  181. {
  182.     outp(0x43, TIMERMODE);
  183.     outp(0x40, count & 0xFF);
  184.     outp(0x40, (count >> 8) & 0xFF);
  185. }
  186.  
  187.  
  188.  
  189. /****************************************************************************\
  190. *
  191. * Function:     void NextTimer(void)
  192. *
  193. * Description:  Sets everything up for the next timer interrupt
  194. *
  195. \****************************************************************************/
  196.  
  197. static void NextTimer(void)
  198. {
  199.     if ( scrSync )
  200.     {
  201.         /* Timer is synchronized to screen: */
  202.         if ( playSD && mSyncScreen )
  203.         {
  204.             if ( playCount < scrCount )
  205.             {
  206.                 if ( playCount < 10 )
  207.                     playCount = 10;
  208.  
  209.                 /* Player interrupt, please */
  210.                 tmrState = tmrPlayer;
  211.                 SetCount(playCount);
  212.                 return;
  213.             }
  214.         }
  215.  
  216.         if ( scrCount < 10 )
  217.             scrCount = 10;
  218.  
  219.         /* Screen interrupt, please: */
  220.         tmrState = tmrScreen;
  221.         SetCount(scrCount);
  222.         return;
  223.     }
  224.  
  225.     if ( playSD )
  226.     {
  227.         if ( playCount < 10 )
  228.             playCount = 10;
  229.  
  230.         /* Player interrupt: */
  231.         tmrState = tmrPlayer;
  232.         SetCount(playCount);
  233.         return;
  234.     }
  235.  
  236.     /* System timer: */
  237.     tmrState = tmrSystem;
  238.     SetCount(0);
  239. }
  240.  
  241.  
  242. void CallDOSInt(void);
  243. #pragma aux CallDOSInt = \
  244.     "pushfd" \
  245.     "call fword oldTimer" \
  246.     modify exact [];
  247.  
  248.  
  249. /****************************************************************************\
  250. *
  251. * Function:     void CheckSystemTimer(void)
  252. *
  253. * Description:  Calls the system timer if necessary, send EOI otherwise
  254. *
  255. \****************************************************************************/
  256.  
  257. void CheckSystemTimer(void)
  258. {
  259.     DoSTI();
  260.  
  261.     if ( sysTmrCount < 0x10000 )
  262.     {
  263.         SendEOI();
  264.         return;
  265.     }
  266.  
  267.     while ( sysTmrCount >= 0x10000 )
  268.     {
  269.         sysTmrCount -= 0x10000;
  270.         CallDOSInt();
  271.     }
  272. }
  273.  
  274.  
  275.  
  276.  
  277. /****************************************************************************\
  278. *
  279. * Function:     void PollMIDAS(void)
  280. *
  281. * Description:  Polls MIDAS
  282. *
  283. \****************************************************************************/
  284.  
  285. void PollMIDAS(void)
  286. {
  287.     static int callMP;
  288.     int         i;
  289.  
  290.     if ( (playSD) && (plError == OK) )
  291.     {
  292.         /* Prepare SD for playing: */
  293.         if ( (plError = sdev->StartPlay()) != OK )
  294.         {
  295.             plTimer = 0;
  296.             return;
  297.         }
  298.  
  299.         do
  300.         {
  301.             /* Poll Sound Device: */
  302.             if ( (plError = sdev->Play(&callMP)) != OK )
  303.             {
  304.                 plTimer = 0;
  305.                 return;
  306.             }
  307.  
  308.             if ( callMP )
  309.             {
  310.                 /* Call all music players: */
  311.                 for ( i = 0; i < MAXPLAYERS; i++ )
  312.                 {
  313.                     if ( musicPlayers[i] != NULL )
  314.                     {
  315.                         if ( (plError = (*musicPlayers[i])()) != OK )
  316.                         {
  317.                             plTimer = 0;
  318.                             return;
  319.                         }
  320.                     }
  321.                 }
  322.             }
  323.         } while ( callMP && (sdev->tempoPoll == 0) );
  324.     }
  325. }
  326.  
  327.  
  328. /****************************************************************************\
  329. *
  330. * Function:     void __interrupt __far tmrISR(void)
  331. *
  332. * Description:  The timer ISR
  333. *
  334. \****************************************************************************/
  335.  
  336. void __interrupt __far tmrISR(void)
  337. {
  338.     int         chainDOS = 1;
  339.     long        oldPlayCount;
  340.  
  341.     /* Set DS to ES as well: (stupid Watcom doesn't to this, and then assumes
  342.        ES is valid) */
  343.     SetDStoES();
  344.  
  345.     SetBorder(9);
  346.  
  347.     switch ( tmrState )
  348.     {
  349.         case tmrScreen:
  350.             SetBorder(15);
  351.             DoCLI();                    /* Disable interrupts here */
  352.  
  353.             if ( scrTimer )
  354.             {
  355.                 /* PANIC, screen timer still active! */
  356.                 playCount -= scrCount + scrPVCount;
  357.                 sysTmrCount += scrCount + scrPVCount;
  358.                 scrCount = scrTmrCount;
  359.                 NextTimer();
  360.                 SendEOI();
  361.                 DoSTI();
  362.                 chainDOS = 0;
  363.                 break;
  364.             }
  365.  
  366.             if ( scrSync )
  367.             {
  368.                 SetBorder(14);
  369.  
  370.                 scrTimer = 1;
  371.  
  372.                 if ( mSyncScreen )
  373.                     WaitNoVR();
  374.  
  375.                 if ( preVR != NULL )
  376.                     (*preVR)();
  377.  
  378.                 /* Update timer counters: */
  379.                 sysTmrCount += scrCount + scrPVCount;
  380.                 if ( scrPlayer )
  381.                     playCount = playTmrCount;
  382.                 else
  383.                     playCount -= scrCount + scrPVCount;
  384.                 scrCount = scrTmrCount;
  385.  
  386.                 if ( mSyncScreen )
  387.                     WaitVR();
  388.  
  389.                 if ( immVR != NULL )
  390.                     (*immVR)();
  391.  
  392.                 NextTimer();
  393.                 CheckSystemTimer();
  394.                 scrTimer = 0;
  395.  
  396.                 /* If not synchronizing to screen we need to poll MIDAS
  397.                    here: */
  398.                 if ( (!mSyncScreen) && playSD )
  399.                 {
  400.                     if ( sdev->tempoPoll )
  401.                     {
  402.                         while ( playCount < 0 )
  403.                         {
  404.                             PollMIDAS();
  405.                             playCount += playTmrCount;
  406.                         }
  407.                     }
  408.                     else
  409.                         PollMIDAS();
  410.                 }
  411.  
  412.                 if ( inVR != NULL )
  413.                     (*inVR)();
  414.                 chainDOS = 0;
  415.                 break;
  416.             }
  417.             else
  418.             {
  419.                 /* We shouldn't really be here - check system timer and
  420.                    exit */
  421.                 CheckSystemTimer();
  422.                 chainDOS = 0;
  423.                 break;
  424.             }
  425.             break;
  426.  
  427.         case tmrPlayer:
  428.             if ( plTimer )
  429.             {
  430.                 /* Player timer active - panic! */
  431.                 scrCount -= playCount;
  432.                 sysTmrCount += playCount;
  433.                 playCount = playTmrCount;
  434.                 NextTimer();
  435.                 SendEOI();
  436.                 DoSTI();
  437.                 chainDOS = 0;
  438.                 break;
  439.             }
  440.  
  441.             plTimer = 1;
  442.             scrCount -= playCount;
  443.             sysTmrCount += playCount;
  444.  
  445.             if ( scrPlayer )
  446.                 playCount = 0xFFFF;
  447.             else
  448.                 playCount = playTmrCount;
  449.             NextTimer();
  450.  
  451.             CheckSystemTimer();
  452.             chainDOS = 0;
  453.  
  454.             oldPlayCount = playTmrCount;
  455.  
  456.             PollMIDAS();
  457.  
  458.             /* Check if player timer rate has been updated: */
  459.             if ( (sdev->tempoPoll == 1) && (playTmrCount != oldPlayCount))
  460.             {
  461.                 playCount = playTmrCount;
  462.                 if ( tmrState == tmrPlayer )
  463.                     NextTimer();
  464.             }
  465.  
  466.             plTimer = 0;
  467.             chainDOS = 0;
  468.             break;
  469.  
  470.         case tmrSystem:
  471.         default:
  472.             /* The system timer - set rate to 18.2Hz and chain to DOS: */
  473.             SetCount(0);
  474.             chainDOS = 1;
  475.             break;
  476.     }
  477.  
  478.     SetBorder(0);
  479.  
  480.     if ( chainDOS )
  481.         _chain_intr(oldTimer);
  482. }
  483.  
  484.  
  485.  
  486. /****************************************************************************\
  487. *
  488. * Function:     int tmrInit(void);
  489. *
  490. * Description:  Initializes the timer
  491. *
  492. * Returns:      MIDAS error code
  493. *
  494. \****************************************************************************/
  495.  
  496. int CALLING tmrInit(void)
  497. {
  498.     tmrState = tmrSystem;               /* system timer only */
  499.     playSD = 0;
  500.  
  501.     /* Get old timer interrupt and set our own: */
  502.     oldTimer = _dos_getvect(8);
  503.     _dos_setvect(8, tmrISR);
  504.  
  505.     /* Restart timer at 18.2Hz: */
  506. //    SetCount(0);
  507.  
  508.     return OK;
  509. }
  510.  
  511.  
  512.  
  513.  
  514. /****************************************************************************\
  515. *
  516. * Function:     int tmrClose(void);
  517. *
  518. * Description:  Uninitializes the timer.
  519. *
  520. * Returns:      MIDAS error code
  521. *
  522. \****************************************************************************/
  523.  
  524. int CALLING tmrClose(void)
  525. {
  526.     /* Set DOS default timer mode and 18.2Hz rate: */
  527.     outp(0x43, 0x36);
  528.     outp(0x40, 0);
  529.     outp(0x40, 0);
  530.  
  531.     /* Restore old interrupt vector: */
  532.     _dos_setvect(8, oldTimer);
  533.  
  534.     /* Set DOS default timer mode and 18.2Hz rate: */
  535.     outp(0x43, 0x36);
  536.     outp(0x40, 0);
  537.     outp(0x40, 0);
  538.  
  539.     return OK;
  540. }
  541.  
  542.  
  543.  
  544.  
  545. /****************************************************************************\
  546. *
  547. * Function:     int tmrGetScrSync(unsigned *scrSync);
  548. *
  549. * Description:  Calculates the screen synchronization value for timer
  550. *
  551. * Input:        unsigned *scrSync       pointer to screen synchronization
  552. *                                       value
  553. *
  554. * Returns:      MIDAS error code.
  555. *               Screen syncronization value used with tmrSyncScr() is stored
  556. *               in *scrSync.
  557. *
  558. \****************************************************************************/
  559.  
  560. int CALLING tmrGetScrSync(unsigned *scrSync)
  561. {
  562.     int         failCount = 0, success = 0;
  563.     long        count1, count2, prevCount = 0, count;
  564.  
  565.     if ( !mSyncScreen )
  566.     {
  567.         /* No sync - just return the default frame rate: */
  568.         *scrSync = 119318000 / mDefaultFramerate;
  569.         return OK;
  570.     }
  571.  
  572.     DoCLI();
  573.  
  574.     while ( (failCount < 4) && (success != 1) )
  575.     {
  576.         WaitNextVR();
  577.         outp(0x43, 0x36);
  578.         outp(0x40, 0);
  579.         outp(0x40, 0);
  580.         WaitNextVR();
  581.         outp(0x43, 0);
  582.         count1 = inp(0x40);
  583.         count1 |= (inp(0x40)) << 8;
  584.         count1 = 0x10000-count1;
  585.  
  586.         WaitNextVR();
  587.         outp(0x43, 0x36);
  588.         outp(0x40, 0);
  589.         outp(0x40, 0);
  590.         WaitNextVR();
  591.         outp(0x43, 0);
  592.         count2 = inp(0x40);
  593.         count2 |= (inp(0x40)) << 8;
  594.         count2 = 0x10000-count2;
  595.  
  596.         if ( ((count2 - count1) > 2) || ((count2 - count1) < -2) )
  597.         {
  598.             failCount++;
  599.         }
  600.         else
  601.         {
  602.             count = count1 >> 1;
  603.             if ( ((prevCount - count) <= 2) && ((prevCount - count) >= -2) )
  604.                 success = 1;
  605.             else
  606.             {
  607.                 prevCount = count;
  608.                 failCount++;
  609.             }
  610.         }
  611.     }
  612.  
  613.     if ( success )
  614.     {
  615.         /* We got the synchronization value! */
  616.         *scrSync = count;
  617.     }
  618.     else
  619.     {
  620.         /* Couldn't synchronize - turn sync off and return default
  621.            frame rate: */
  622.         mSyncScreen = 0;
  623.         *scrSync = 119318000 / mDefaultFramerate;
  624.     }
  625.  
  626.     DoSTI();
  627.  
  628.     return OK;
  629. }
  630.  
  631.  
  632.  
  633.  
  634. /****************************************************************************\
  635. *
  636. * Function:     int tmrPlaySD(SoundDevice *SD);
  637. *
  638. * Description:  Starts playing sound with a Sound Device ie. calling its
  639. *               Play() function in the update rate, which is set to
  640. *               50Hz.
  641. *
  642. * Input:        SoundDevice *SD         Sound Device that will be used
  643. *
  644. * Returns:      MIDAS error code.
  645. *
  646. \****************************************************************************/
  647.  
  648. int CALLING tmrPlaySD(SoundDevice *SD)
  649. {
  650.     int         i;
  651.  
  652.     sdev = SD;
  653.  
  654.     /* Reset all music player pointers to NULL: */
  655.     for ( i = 0; i < MAXPLAYERS; i++ )
  656.         musicPlayers[i] = NULL;
  657.  
  658.     if ( !sdev->tempoPoll )
  659.     {
  660.         if ( scrSync && mSyncScreen )
  661.         {
  662.             /* We are synchronizing to screen and have a non-tempoPoll SD -
  663.                call the music player a 1/4th of a frame after the retrace: */
  664.             scrPlayer = 1;
  665.             playTmrCount = playCount = scrTmrCount / 4;
  666.         }
  667.         else
  668.         {
  669.             /* No tempo-polling and no screen-sync - poll at 100Hz: */
  670.             playTmrCount = playCount = 1193180 / 100;
  671.             scrPlayer = 0;
  672.         }
  673.     }
  674.     else
  675.     {
  676.         /* Tempo-polling Sound Device - set initially to 50Hz: */
  677.         playTmrCount = playCount = 1193180 / 50;
  678.         scrPlayer = 0;
  679.     }
  680.  
  681.     plTimer = 0;
  682.     plError = 0;
  683.  
  684.     /* Start playing: */
  685.     DoCLI();
  686.  
  687.     if ( tmrState == tmrSystem )
  688.     {
  689.         tmrState = tmrPlayer;
  690.         SetCount(playCount);
  691.         sysTmrCount = 0;
  692.     }
  693.  
  694.     playSD = 1;
  695.  
  696.     DoSTI();
  697.  
  698.     return OK;
  699. }
  700.  
  701.  
  702.  
  703.  
  704. /****************************************************************************\
  705. *
  706. * Function:     int tmrStopSD(void);
  707. *
  708. * Description:  Stops playing sound with the Sound Device.
  709. *
  710. * Returns:      MIDAS error code.
  711. *
  712. \****************************************************************************/
  713.  
  714. int CALLING tmrStopSD(void)
  715. {
  716.     DoCLI();
  717.  
  718.     playSD = 0;
  719.  
  720.     if ( !scrSync )
  721.     {
  722.         /* No screen sync - only system timer now: */
  723.         tmrState = tmrSystem;
  724.         SetCount(0);
  725.     }
  726.  
  727.     DoSTI();
  728.  
  729.     return OK;
  730. }
  731.  
  732.  
  733.  
  734.  
  735. /****************************************************************************\
  736. *
  737. * Function:     int tmrPlayMusic(void *play, int *playerNum);
  738. *
  739. * Description:  Starts playing music with the timer.
  740. *
  741. * Input:        void *play              Pointer to music playing function,
  742. *                                       must return MIDAS error codes
  743. *               int *playerNum          Pointer to player number, used
  744. *                                       for stopping music
  745. *
  746. * Returns:      MIDAS error code. Player number is written to *playerNum.
  747. *
  748. * Notes:        There can be a maximum of 16 music players active at the
  749. *               same time.
  750. *
  751. \****************************************************************************/
  752.  
  753. int CALLING tmrPlayMusic(int CALLING (*play)(), int *playerNum)
  754. {
  755.     int         i;
  756.  
  757.  
  758.     /* Try to find a free music player: */
  759.     for ( i = 0; i < MAXPLAYERS; i++ )
  760.     {
  761.         if ( musicPlayers[i] == NULL )
  762.             break;
  763.     }
  764.  
  765.     if ( i >= MAXPLAYERS )
  766.     {
  767.         /* No free player found: */
  768.         ERROR(errOutOfResources, ID_tmrPlayMusic);
  769.         return errOutOfResources;
  770.     }
  771.  
  772.     /* Free player found - store the pointer and return player ID: */
  773.     musicPlayers[i] = play;
  774.     *playerNum = i;
  775.  
  776.     return OK;
  777. }
  778.  
  779.  
  780.  
  781.  
  782. /****************************************************************************\
  783. *
  784. * Function:     int tmrStopMusic(int playerNum);
  785. *
  786. * Description:  Stops playing music with the timer.
  787. *
  788. * Input:        int playerNum           Number of player to be stopped.
  789. *
  790. * Returns:      MIDAS error code
  791. *
  792. \****************************************************************************/
  793.  
  794. int CALLING tmrStopMusic(int playerNum)
  795. {
  796.     musicPlayers[playerNum] = NULL;
  797.  
  798.     return OK;
  799. }
  800.  
  801.  
  802.  
  803.  
  804. /****************************************************************************\
  805. *
  806. * Function:     int tmrSyncScr(unsigned sync, void (*preVR)(),
  807. *                   void (*immVR)(), void (*inVR)());
  808. *
  809. * Description:  Synchronizes the timer to screen refresh.
  810. *
  811. * Input:        unsigned sync           Screen synchronization value returned
  812. *                                       by tmrGetScrSync().
  813. *               void (*preVR)()         Pointer to the routine that will be
  814. *                                       called BEFORE Vertical Retrace
  815. *               void (*immVR)()         Pointer to the routine that will be
  816. *                                       called immediately after Vertical
  817. *                                       Retrace starts
  818. *               void (*inVR)()          Pointer to the routine that will be
  819. *                                       called some time during Vertical
  820. *                                       Retrace
  821. *
  822. * Returns:      MIDAS error code
  823. *
  824. * Notes:        preVR() and immVR() functions must be as short as possible
  825. *               and do nothing else than update counters or set some VGA
  826. *               registers to avoid timer synchronization problems. inVR()
  827. *               can take a longer time and can be used for, for example,
  828. *               setting the palette.
  829. *
  830. *               Remember to use the correct calling convention for the xxVR()
  831. *               routines! (pascal for Pascal programs, cdecl otherwise).
  832. *
  833. \****************************************************************************/
  834.  
  835. int CALLING tmrSyncScr(unsigned sync, void CALLING (*_preVR)(),
  836.     void CALLING (*_immVR)(), void CALLING (*_inVR)())
  837. {
  838.     /* We don't want to get disturbed right now: */
  839.     DoCLI();
  840.  
  841.     /* Save the function pointers: */
  842.     preVR = _preVR;
  843.     immVR = _immVR;
  844.     inVR = _inVR;
  845.  
  846.     if ( mSyncScreen )
  847.     {
  848.         scrTmrCount = FRAMETIME * sync / 1000;
  849.         scrPVCount = sync - scrTmrCount;
  850.     }
  851.     else
  852.     {
  853.         scrTmrCount = sync;
  854.         scrPVCount = 0;
  855.     }
  856.  
  857.     /* Next interrupt will be screen - synchronize to screen and start: */
  858.     scrCount = scrTmrCount;
  859.     tmrState = tmrScreen;
  860.     scrSync = 1;
  861.     WaitNextVR();
  862.     SetCount(scrCount);
  863.  
  864.     /* If we are synchronizing to the screen fully and the card is not
  865.        tempopolling, start screen sync playing: */
  866.     if ( mSyncScreen && (!sdev->tempoPoll) )
  867.     {
  868.         playCount = playTmrCount = scrTmrCount / 4;
  869.         scrPlayer = 1;
  870.     }
  871.  
  872.     DoSTI();
  873.  
  874.     return OK;
  875. }
  876.  
  877.  
  878.  
  879.  
  880. /****************************************************************************\
  881. *
  882. * Function:     int tmrStopScrSync(void);
  883. *
  884. * Description:  Stops synchronizing the timer to the screen.
  885. *
  886. * Returns:      MIDAS error code
  887. *
  888. \****************************************************************************/
  889.  
  890. int CALLING tmrStopScrSync(void)
  891. {
  892.     DoCLI();
  893.  
  894.     if ( scrPlayer )
  895.     {
  896.         /* Player was synchronized to screen - restart at 100Hz: */
  897.         playCount = playTmrCount = 1193180/100;
  898.         scrPlayer = 0;
  899.     }
  900.  
  901.     scrSync = 0;
  902.     scrTimer = 0;
  903.     NextTimer();
  904.  
  905.     DoSTI();
  906.  
  907.     return OK;
  908. }
  909.  
  910.  
  911.  
  912.  
  913. /****************************************************************************\
  914. *
  915. * Function:     int tmrSetUpdRate(unsigned updRate);
  916. *
  917. * Description:  Sets the timer update rate, ie. the rate at which the music
  918. *               playing routines are called
  919. *
  920. * Input:        unsigned updRate        updating rate, in 100*Hz (5000=50Hz)
  921. *
  922. * Returns:      MIDAS error code
  923. *
  924. \****************************************************************************/
  925.  
  926. int CALLING tmrSetUpdRate(unsigned updRate)
  927. {
  928.     /* Only change if tempopolling: */
  929.     if ( sdev->tempoPoll )
  930.     {
  931.         playTmrCount = 119318000 / updRate;
  932.     }
  933.  
  934.     return OK;
  935. }
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945. /*
  946.  * $Log: dostimer.c,v $
  947.  * Revision 1.6  1997/01/16 18:41:59  pekangas
  948.  * Changed copyright messages to Housemarque
  949.  *
  950.  * Revision 1.5  1996/10/13 16:53:07  pekangas
  951.  * The timer ISR now sets ES to DS
  952.  *
  953.  * Revision 1.4  1996/08/06 18:46:09  pekangas
  954.  * Removed border colors
  955.  *
  956.  * Revision 1.3  1996/08/06 16:51:36  pekangas
  957.  * Fixed SB and timer conflicts
  958.  *
  959.  * Revision 1.2  1996/08/04 18:08:21  pekangas
  960.  * Fixed a nasty bug in tmrGetScrSync - interrupts were left disabled
  961.  *
  962.  * Revision 1.1  1996/06/06 19:28:17  pekangas
  963.  * Initial revision
  964.  *
  965. */
  966.